﻿// Fill out your copyright notice in the Description page of Project Settings.


#include "MultiThreading/TaskGraph.h"

void ATaskGraphActor::BeginPlay()
{
	Super::BeginPlay();
	ActiveTask();
}

FTaskGraphItem ATaskGraphActor::CreateGraphTask(const FString& ThreadName, const TArray<FTaskGraphItem>& Prerequisites, const TArray<FTaskGraphItem>& ChildTasks, bool DispatchWhenReady)
{
	FGraphEventArray PrerequisiteEvents; // 依赖事件
	TArray<TGraphTask<FTaskGraphWithPrerequisitesAndChild>*> ChildGraphTask; // 子任务
	// UE_LOG(LogTemp, Warning, TEXT("Task[%s] is Created!"), *ThreadName);
	if (Prerequisites.Num() > 0)
	{
		for (FTaskGraphItem item : Prerequisites) // 结构体数组提取依赖事件
		{
			if (item.m_GraphEventRef)
			{
				PrerequisiteEvents.Add(item.m_GraphEventRef);
				// UE_LOG(LogTemp, Warning, TEXT("Task[%s] wait Task[%s]!"), *ThreadName, *item.m_ThreadName);
			} else if (item.m_GraphTask)
			{
				PrerequisiteEvents.Add(item.m_GraphTask->GetCompletionEvent());
				// UE_LOG(LogTemp, Warning, TEXT("Task[%s] wait Task[%s]!"), *ThreadName, *item.m_ThreadName);
			}
		}
	}
	if (ChildTasks.Num() > 0)
	{
		for (FTaskGraphItem item : ChildTasks) // 提取子任务
		{
			if (item.m_GraphTask)
			{
				ChildGraphTask.Add(item.m_GraphTask);
				// UE_LOG(LogTemp, Warning, TEXT("Task[%s] is Task[%s] child task!"), *item.m_ThreadName, *ThreadName);
			}
		}
	}

	FGraphTaskDelegate GraphTaskDelegate = FGraphTaskDelegate::CreateUObject(this, &ATaskGraphActor::OnTaskFinished);
	if (DispatchWhenReady)
	{
		// 创建立即执行的任务，返回结构体参数
		return FTaskGraphItem(ThreadName, TGraphTask<FTaskGraphWithPrerequisitesAndChild>::CreateTask(&PrerequisiteEvents).ConstructAndDispatchWhenReady(ThreadName, ChildGraphTask, GraphTaskDelegate));
	}
	// 创建任务后挂起，等待触发，返回结构体参数
	return FTaskGraphItem(ThreadName, nullptr, TGraphTask<FTaskGraphWithPrerequisitesAndChild>::CreateTask(&PrerequisiteEvents).ConstructAndHold(ThreadName, ChildGraphTask, GraphTaskDelegate));
}

void ATaskGraphActor::TriggerGraphTask(FTaskGraphItem TaskGraphItem)
{
	if (TaskGraphItem.m_GraphTask)
	{
		TaskGraphItem.m_GraphTask->Unlock();
		// UE_LOG(LogTemp, Warning, TEXT("Task %s Trigger!"), *TaskGraphItem.m_ThreadName);
	}
}

void ATaskGraphActor::OnTaskFinished_Implementation(const FString& message)
{
	// // UE_LOG(LogTemp, Warning, TEXT("Task is Finished!"), *message);
}

void ATaskGraphActor::ActiveTask()
{
	TArray<FTaskGraphItem> TempBParentTask, TempBChildTask, TempCParentTask, TempCChildTask;
	A0 = CreateGraphTaskPure("A0", false);
	A1 = CreateGraphTaskPure("A1", false);
	TempBParentTask.Emplace(A0);
	TempBParentTask.Emplace(A1);
	B0 = CreateGraphTaskPure("B0", false);
	B1 = CreateGraphTaskPure("B1", false);
	TempBChildTask.Emplace(B0);
	TempBChildTask.Emplace(B1);
	B = CreateGraphTask("B", TempBParentTask, TempBChildTask, true);
	TempCParentTask.Emplace(B);
	C0 = CreateGraphTask("C0", TempCParentTask, TempCChildTask, true);
	C1 = CreateGraphTask("C1", TempCParentTask, TempCChildTask, true);
	TriggerGraphTask(A0);
	TriggerGraphTask(A1);
}
